//===----------------------------------------------------------------------===//
//
//                         BusTub
//
// b_plus_tree_insert_test.cpp
//
// Identification: test/storage/b_plus_tree_insert_test.cpp
//
// Copyright (c) 2015-2021, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <algorithm>
#include <cstdio>

#include "buffer/buffer_pool_manager_instance.h"
#include "gtest/gtest.h"
#include "storage/index/b_plus_tree.h"
#include "test_util.h"  // NOLINT

namespace bustub {

// TEST(BPlusTreeTests, InsertTest1) {
//   // create KeyComparator and index schema
//   auto key_schema = ParseCreateStatement("a bigint");
//   GenericComparator<8> comparator(key_schema.get());

//   auto *disk_manager = new DiskManager("test.db");
//   BufferPoolManager *bpm = new BufferPoolManagerInstance(50, disk_manager);
//   // create b+ tree
//   BPlusTree<GenericKey<8>, RID, GenericComparator<8>> tree("foo_pk", bpm, comparator, 2, 3);
//   GenericKey<8> index_key;
//   RID rid;
//   // create transaction
//   auto *transaction = new Transaction(0);

//   // create and fetch header_page
//   page_id_t page_id;
//   auto header_page = bpm->NewPage(&page_id);
//   ASSERT_EQ(page_id, HEADER_PAGE_ID);
//   (void)header_page;

//   int64_t key = 42;
//   int64_t value = key & 0xFFFFFFFF;
//   rid.Set(static_cast<int32_t>(key), value);
//   index_key.SetFromInteger(key);
//   tree.Insert(index_key, rid, transaction);

//   auto root_page_id = tree.GetRootPageId();
//   // std::cout<<"after get root"<<std::endl;
//   auto root_page = reinterpret_cast<BPlusTreePage *>(bpm->FetchPage(root_page_id)->GetData());
//   ASSERT_NE(root_page, nullptr);
//   ASSERT_TRUE(root_page->IsLeafPage());

//   auto root_as_leaf = reinterpret_cast<BPlusTreeLeafPage<GenericKey<8>, RID, GenericComparator<8>> *>(root_page);
//   ASSERT_EQ(root_as_leaf->GetSize(), 1);
//   ASSERT_EQ(comparator(root_as_leaf->KeyAt(0), index_key), 0);
//   // std::cout<<root_as_leaf->KeyAt(1)<<std::endl;
//   // std::cout<<index_key<<std::endl;

//   bpm->UnpinPage(root_page_id, false);
//   bpm->UnpinPage(HEADER_PAGE_ID, true);
//   delete transaction;
//   delete disk_manager;
//   delete bpm;
//   remove("test.db");
//   remove("test.log");
// }   
//p  reinterpret_cast<InternalPage*>(this->buffer_pool_manager_->FetchPage(6,0)->GetData())->array_[1]  
// p  reinterpret_cast<LeafPage*>(this->buffer_pool_manager_->FetchPage(2,0)->GetData())->GetParentPageId() 
// //bustub::BPlusTreeTests_InsertTest2_Test::TestBody
// //bustub::BPlusTree<bustub::GenericKey<8ul>, bustub::RID, bustub::GenericComparator<8ul> >::Insert
// //bustub::BPlusTree<bustub::GenericKey<8ul>, bustub::RID, bustub::GenericComparator<8ul> >::FindLeaf
//bustub::BufferPoolManagerInstance::NewPgImp
TEST(BPlusTreeTests, InsertTest2) {
  // create KeyComparator and index schema
  auto key_schema = ParseCreateStatement("a bigint");
  GenericComparator<8> comparator(key_schema.get());

  auto *disk_manager = new DiskManager("test.db");
  BufferPoolManager *bpm = new BufferPoolManagerInstance(5, disk_manager);
  // create b+ tree
  BPlusTree<GenericKey<8>, RID, GenericComparator<8>> tree("foo_pk", bpm, comparator, 2, 3);
  GenericKey<8> index_key;
  RID rid;
  // create transaction
  auto *transaction = new Transaction(0);

  // create and fetch header_page
  page_id_t page_id;
  auto header_page = bpm->NewPage(&page_id);
  (void)header_page;

  std::vector<int64_t> keys ={1, 2, 3, 4};

  for (auto key : keys) {
    int64_t value = key & 0xFFFFFFFF;
    rid.Set(static_cast<int32_t>(key >> 32), value);
    index_key.SetFromInteger(key);
    tree.Insert(index_key, rid, transaction);
  }
  std::cout<<"after insert"<<std::endl;
  std::vector<RID> rids;
  for (auto key : keys) {
    rids.clear();
    index_key.SetFromInteger(key);
    tree.GetValue(index_key, &rids);//问题发生在查询25时，pageid为46的页面，size不正确，应该为1，但是变成2，导致查询到后面的数据，Fetch page的时候找不到
    EXPECT_EQ(rids.size(), 1);
    int64_t value = key & 0xFFFFFFFF;
    EXPECT_EQ(rids[0].GetSlotNum(), value);
  }

  int64_t size = 0;
  bool is_present;

  for (auto key : keys) {
    rids.clear();
    index_key.SetFromInteger(key);
    is_present = tree.GetValue(index_key, &rids);

    EXPECT_EQ(is_present, true);
    EXPECT_EQ(rids.size(), 1);
    EXPECT_EQ(rids[0].GetPageId(), 0);
    EXPECT_EQ(rids[0].GetSlotNum(), key);
    size = size + 1;
  }

  EXPECT_EQ(size, keys.size());

  bpm->UnpinPage(HEADER_PAGE_ID, true);
  delete transaction;
  delete disk_manager;
  delete bpm;
  remove("test.db");
  remove("test.log");
}

// TEST(BPlusTreeTests,InsertTest3) {
//   // create KeyComparator and index schema
//   auto key_schema = ParseCreateStatement("a bigint");
//   GenericComparator<8> comparator(key_schema.get());

//   auto *disk_manager = new DiskManager("test.db");
//   BufferPoolManager *bpm = new BufferPoolManagerInstance(50, disk_manager);
//   // create b+ tree
//   BPlusTree<GenericKey<8>, RID, GenericComparator<8>> tree("foo_pk", bpm, comparator);
//   GenericKey<8> index_key;
//   RID rid;
//   // create transaction
//   auto *transaction = new Transaction(0);

//   // create and fetch header_page
//   page_id_t page_id;
//   auto header_page = bpm->NewPage(&page_id);
//   ASSERT_EQ(page_id, HEADER_PAGE_ID);
//   (void)header_page;

//   std::vector<int64_t> keys = {5, 4, 3, 2, 1};
//   for (auto key : keys) {
//     int64_t value = key & 0xFFFFFFFF;
//     rid.Set(static_cast<int32_t>(key >> 32), value);
//     index_key.SetFromInteger(key);
//     tree.Insert(index_key, rid, transaction);
//   }

//   std::vector<RID> rids;
//   for (auto key : keys) {
//     rids.clear();
//     index_key.SetFromInteger(key);
//     tree.GetValue(index_key, &rids);
//     EXPECT_EQ(rids.size(), 1);

//     int64_t value = key & 0xFFFFFFFF;
//     EXPECT_EQ(rids[0].GetSlotNum(), value);
//   }

//   int64_t start_key = 1;
//   int64_t current_key = start_key;
//   index_key.SetFromInteger(start_key);
//   for (auto iterator = tree.Begin(index_key); iterator != tree.End(); ++iterator) {
//     auto location = (*iterator).second;
//     EXPECT_EQ(location.GetPageId(), 0);
//     EXPECT_EQ(location.GetSlotNum(), current_key);
//     std::cout<<current_key<<std::endl;
//     current_key = current_key + 1;
//   }

//   EXPECT_EQ(current_key, keys.size() + 1);

//   start_key = 3;
//   current_key = start_key;
//   index_key.SetFromInteger(start_key);
//   for (auto iterator = tree.Begin(index_key); iterator != tree.End(); ++iterator) {
//     auto location = (*iterator).second;
//     EXPECT_EQ(location.GetPageId(), 0);
//     EXPECT_EQ(location.GetSlotNum(), current_key);
//     current_key = current_key + 1;
//   }

//   bpm->UnpinPage(HEADER_PAGE_ID, true);
//   delete transaction;
//   delete disk_manager;
//   delete bpm;
//   remove("test.db");
//   remove("test.log");
// }
}  // namespace bustub
